package cn.fabrice.service.impl;

import cn.fabrice.common.ErrorCode;
import cn.fabrice.constant.MessageConstant;
import cn.fabrice.constant.UserConstant;
import cn.fabrice.dto.UserLoginDTO;
import cn.fabrice.dto.UserQueryDTO;
import cn.fabrice.exception.BusinessException;
import cn.fabrice.service.UserService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.fabrice.model.User;
import cn.fabrice.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* @author wangwenhui
* @description 针对表【user(用户表 )】的数据库操作Service实现
* @createDate 2024-03-06 23:59:12
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>  implements UserService {

    @Autowired
    private UserMapper userMapper;



    /**
     * 用户注册
     * @param account 用户账号
     * @param password 用户密码
     * @return 新用户id
     */
    @Override
    public Long userRegister(String account, String password,String checkPassword) {
        //1. 校验
        if(StringUtils.isAnyBlank(account,password)){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR);
        }
        if(!password.equals(checkPassword)){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"两次输入的密码不相同");
        }
        if (account.length() < 4){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"账号长度不能小于4");
        }
        if(password.length() < 6){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"密码长度不能小于6");
        }
        //特殊字符校验
        Pattern pattern= Pattern.compile("^[a-zA-Z0-9_]+$");
        boolean flag = pattern.matcher(account).matches();
        if(!flag){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"账号只允许字母、数字、下划线");
        }
        //账户不能重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account",account);
        int count = this.count(queryWrapper);
        if(count > 0){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"该账号已存在");
        }
        //密码加密
        User user = new User();
        String salt = UUID.randomUUID().toString();
        String newPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        user.setSalt(salt);
        user.setPassword(newPassword);
        user.setAccount(account);
        user.setName(account); //默认设置初始时用户名与账号相同
        return (long) userMapper.insert(user);
    }

    /**
     * 用户登录
     * @param account 用户账号
     * @param password 用户密码
     * @param request 响应
     * @return
     */
    @Override
    public User userLogin(String account, String password, HttpServletRequest request) {
        //1. 校验
        if(StringUtils.isAnyBlank(account,password)){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR);
        }
        if (account.length() < 4){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"账号长度不能小于4");
        }
        if(password.length() < 6){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"密码长度不能小于6");
        }
        //特殊字符校验
        Pattern pattern= Pattern.compile("^[a-zA-Z0-9_]+$");
        boolean flag = pattern.matcher(account).matches();
        if(!flag){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,"账号只允许字母、数字、下划线");
        }

        //2. 从数据库中查找，对比
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account",account);
        User DBuser = userMapper.selectOne(queryWrapper);
        //账号不存在
        if(DBuser == null){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,MessageConstant.ACCOUNT_NOT_FOUND);
        }
        //账号被禁用
        if(DBuser.getStatus() == UserConstant.STATUS_DISABLE){
            throw new BusinessException(ErrorCode.IS_DISABLED);
        }
        //密码错误
        String userPassword = DigestUtils.md5DigestAsHex((DBuser.getSalt() + password).getBytes());
        if (!DBuser.getPassword().equals(userPassword) ){
            throw new BusinessException(ErrorCode.PARAMETER_ERROR,MessageConstant.PASSWORD_ERROR);
        }
        //3.脱敏返回
        User user = new User();
        BeanUtils.copyProperties(DBuser,user);
        User safetyUser = getSafetyUser(user);

        request.getSession().setAttribute(UserConstant.USER_LOGIN,safetyUser);
        return safetyUser;
    }

    /**
     * 用户查询
     * @param userQueryDTO
     * @return
     */
    @Override
    public List<User> searchPage(UserQueryDTO userQueryDTO) {
        String name = userQueryDTO.getName();
        Integer status = userQueryDTO.getStatus();
        Integer type = userQueryDTO.getType();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name",name);
        queryWrapper.eq(status!= null,"status",status);
        queryWrapper.eq(type!=null,"name",type);

        List<User> users = userMapper.selectList(queryWrapper);
        users.stream().map(user -> {
            return getSafetyUser(user);
        }).collect(Collectors.toList());
        return users;
    }

    /**
     * 根据id删除
     * @param id
     * @return
     */
    @Override
    public boolean deleteById(Long id) {
        return userMapper.deleteById(id) > 0;
    }

    /**
     * 用户脱敏
     * @param user
     * @return
     */
    @Override
    public User getSafetyUser(User user) {
        if (user == null){
            throw new BusinessException(ErrorCode.NOLL_ERROR);
        }
        User safetyUser = new User();
        BeanUtils.copyProperties(user,safetyUser);
        safetyUser.setPassword("******");
        safetyUser.setSalt("******");
        return safetyUser;
    }

    /**
     * 用户退出
     * @param request
     * @return
     */
    @Override
    public Integer userLogout(HttpServletRequest request) {
        request.getSession().removeAttribute(UserConstant.USER_LOGIN);
        return 1;
    }

}




